package com.whh.starter.config;


import cn.hutool.core.util.IdUtil;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.MDC;

import java.time.LocalDateTime;
import java.time.ZoneId;

import static com.whh.starter.config.constant.CommonConstants.CORRELATION_ID;


@Data
public class RequestContext {

    private String correlationId;

    private LocalDateTime startTime;

    private String operationName;

    private SystemException systemException;

    private CodeMapper errResultCodeMapper;

    private String secretKey;

    private static final ThreadLocal<RequestContext> REQUEST_CONTEXT_POOL = new ThreadLocal<>();

    private RequestContext() {

    }

    public static RequestContext getCurrentContext() {
        return REQUEST_CONTEXT_POOL.get();
    }

    public static void createContext(String correlationId) {
        REQUEST_CONTEXT_POOL.remove();
        MDC.clear();
        RequestContext context = new RequestContext();
        context.startTime = LocalDateTime.now();
        if (StringUtils.isEmpty(correlationId)) {
            correlationId = IdUtil.fastSimpleUUID();
        }
        context.correlationId = correlationId;
        MDC.put(CORRELATION_ID, correlationId);
        REQUEST_CONTEXT_POOL.set(context);
    }

    public static void cleanContext() {
        REQUEST_CONTEXT_POOL.remove();
        MDC.clear();
    }

    public void operationName(String operationName) {
        this.operationName = operationName;
    }

    public void error(SystemException systemException) {
        this.systemException = systemException;
        if (systemException != null) {
            this.errResultCodeMapper = systemException.resultCodeMapper();
        }
    }

    public void error(DefaultCodeMapper errResultCodeMapper) {
        this.errResultCodeMapper = errResultCodeMapper;
    }

    public long costTime() {
        return System.currentTimeMillis() - startTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
    }

    public CodeMapper errorResult() {
        return this.errResultCodeMapper;
    }

    public void secretKey(String secretKey) {
        this.secretKey = secretKey;
    }

}

